package com.wx.tnsadmin.aspect;

import com.alibaba.fastjson.JSON;
import com.wx.tnsadmin.pojo.SysLog;
import com.wx.tnsadmin.service.LogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.UUID;

/**
 * @Author:LLH
 * @Date:2020/8/19
 */
@Aspect
@Component
public class SystemLogAspect {

    private static Logger logger = LoggerFactory.getLogger ( SystemLogAspect.class );
    /**
     * 操作数据库
     */
    @Autowired
    private LogService addLogService;


    /*定义切点
     *  Controller层切点 注解拦截
     */
    @Pointcut("@annotation(com.wx.tnsadmin.annotation.Log)")
    public void logPointCut () {
    }

    /*切面*/
    @Around(value = "logPointCut()")
    public Object around ( ProceedingJoinPoint joinPoint ) {
        Object result = null;
        long beginTime = System.currentTimeMillis ( );
        try {
            // 执行方法
            result = joinPoint.proceed ( );
        } catch (Throwable e) {
            e.printStackTrace ( );
        }
        // 执行时长(毫秒)
        long time = System.currentTimeMillis ( ) - beginTime;
        // 保存日志
        saveLog ( joinPoint,time );
        logger.info ( "响应时间: " + time + "ms" );
        return result;
    }

    private void saveLog ( ProceedingJoinPoint joinPoint,long time ) {
        logger.info ( "调用日志监控" );
        SysLog adminLog = new SysLog ( );
        /*从切面值入点获取植入点方法*/
        MethodSignature signature = (MethodSignature) joinPoint.getSignature ( );
        /*获取切入点方法*/
        Method method = signature.getMethod ( );
        /*获取方法上的值*/
        com.wx.tnsadmin.annotation.Log systemControllerLog = method.getAnnotation ( com.wx.tnsadmin.annotation.Log.class );
        /*保存操作事件*/
        if (systemControllerLog != null) {
            String operation = systemControllerLog.operation ( );

            /*保存日志类型*/
            adminLog.setOperation ( operation );
            /*打印*/
            logger.info ( "操作事件 :" + operation );

        }
        /*获取请求体内容*/
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes ( )).getRequest ( );

        String remoteAddr = this.getIpAddress ( request );/*获取ip地址*/
        String className = joinPoint.getTarget ( ).getClass ( ).getName ( );/*获取请求的类名*/
        String methodName = method.getName ( );/*获取请求的方法名*/
        String requestMethod = request.getMethod ( );/*获取请求方式*/
        String requestUri = request.getRequestURI ( );/*获取映射地址*/

        /*获取ID*/
        String id = UUID.randomUUID ( ).toString ( ).replace ( "-","" );
        adminLog.setId ( id );
        logger.info ( "操作ID为:" + id );

        adminLog.setIp ( remoteAddr );
        logger.info ( "请求IP为:" + remoteAddr );

        adminLog.setUrl ( className + "." + methodName );
        logger.info ( "请求路径为:" + className + "." + methodName );

        adminLog.setMethod ( requestMethod );
        logger.info ( "请求方式为:" + requestMethod );

        adminLog.setMappedaddr ( requestUri );
        logger.info ( "映射路径为:" + requestUri );

        adminLog.setCreatetime ( new Date ( ) );
        logger.info ( "创建时间为:" + new Date ( ) );


        /*获取参数*/
        Object[] args = joinPoint.getArgs ( );
        if (args != null) {
            for (Object obj : args) {
                String params = JSON.toJSONString ( args );
                adminLog.setParams ( params );
                logger.info ( "请求参数为：" + params );

            }
        }
        adminLog.setUsername ( "admin" );

        adminLog.setTime ( (int) time );

        addLogService.save ( adminLog );


    }

    /*ip处理工具类*/
//    public String getIpAddress ( HttpServletRequest request ) {
//
//        String ipAddress = request.getHeader ( "x-forwarded-for" );
//        if (ipAddress == null || ipAddress.length ( ) == 0 || "unknown".equalsIgnoreCase ( ipAddress )) {
//            ipAddress = request.getHeader ( "Proxy-Client-IP" );
//        }
//        if (ipAddress == null || ipAddress.length ( ) == 0 || "unknown".equalsIgnoreCase ( ipAddress )) {
//            ipAddress = request.getHeader ( "WL-Proxy-Client-IP" );
//        }
//        if (ipAddress == null || ipAddress.length ( ) == 0 || "unknown".equalsIgnoreCase ( ipAddress )) {
//            ipAddress = request.getRemoteAddr ( );
//            if (ipAddress.equals ( "127.0.0.1" ) || ipAddress.equals ( "0:0:0:0:0:0:0:1" )) {
//                //根据网卡取本机配置的IP
//                InetAddress inet = null;
//                try {
//                    inet = InetAddress.getLocalHost ( );
//                } catch (UnknownHostException e) {
//                    e.printStackTrace ( );
//                }
//                ipAddress = inet.getHostAddress ( );
//            }
//        }
//        //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
//        if (ipAddress != null && ipAddress.length ( ) > 15) { //"***.***.***.***".length() = 15
//            if (ipAddress.indexOf ( "," ) > 0) {
//                ipAddress = ipAddress.substring ( 0,ipAddress.indexOf ( "," ) );
//            }
//        }
//        return ipAddress;
//    }

    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
        }else if (ip != null && ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = (String) ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
        }
        return ip;
    }
}
